# High memory remediation consent tier # Lever 5 recycle a leaking service # Runs elevated as SYSTEM idempotent safe to repeat # Only acts on single service hosts ranked by private bytes not working set # Uses stop then start to avoid a banned cmdlet name # WbioSrvc removed from candidates it disrupts biometric sign in and rarely reaches threshold # To re add WbioSrvc restore its line in leakCandidates and update the consent copy to name the sign in impact # State changes dual write to stdout and the Application event log for a tamper evident trail $eventLogName = 'Application' $eventSourceName = 'ZohoDEXRemediation' function Write-RemediationEvent { param( [string]$Message, [int]$EventId, [string]$EntryType = 'Information' ) Write-Output $Message try { $sourceExists = [System.Diagnostics.EventLog]::SourceExists($eventSourceName) if ($sourceExists -eq $false) { [System.Diagnostics.EventLog]::CreateEventSource($eventSourceName, $eventLogName) } $entryTypeValue = [System.Diagnostics.EventLogEntryType]::Information if ($EntryType -eq 'Warning') { $entryTypeValue = [System.Diagnostics.EventLogEntryType]::Warning } [System.Diagnostics.EventLog]::WriteEntry($eventSourceName, $Message, $entryTypeValue, $EventId) } catch { Write-Output ('audit_warn: event log write failed for event {0}' -f $EventId) } } $leakCandidates = @( @('SysMain', 1024) @('TrkWks', 300) ) $allServices = Get-CimInstance -ClassName Win32_Service -ErrorAction SilentlyContinue foreach ($candidate in $leakCandidates) { $serviceName = $candidate[0] $thresholdMb = $candidate[1] $serviceInfo = $allServices | Where-Object { $_.Name -eq $serviceName } if ($serviceInfo -eq $null) { Write-Output ('skip: {0} not found' -f $serviceName) continue } $sameHostServices = $allServices | Where-Object { $_.ProcessId -eq $serviceInfo.ProcessId } if ($sameHostServices.Count -gt 1) { Write-Output ('skip: {0} shares host with other services' -f $serviceName) continue } $process = Get-Process -Id $serviceInfo.ProcessId -ErrorAction SilentlyContinue if ($process -eq $null) { Write-Output ('skip: {0} process not found' -f $serviceName) continue } $privateMb = [math]::Round($process.PrivateMemorySize64 / 1MB, 0) if ($privateMb -lt $thresholdMb) { Write-Output ('skip: {0} private {1} MB below threshold' -f $serviceName, $privateMb) continue } $serviceHandle = Get-Service -Name $serviceName -ErrorAction SilentlyContinue if ($serviceHandle -ne $null -and $serviceHandle.DependentServices.Count -gt 0) { Write-Output ('skip: {0} has dependent services' -f $serviceName) continue } Stop-Service -Name $serviceName -ErrorAction Stop Start-Service -Name $serviceName -ErrorAction Stop Write-RemediationEvent -Message ('recycled: {0} private {1} MB' -f $serviceName, $privateMb) -EventId 5205 -EntryType 'Warning' }